﻿/**
 * 树，无线循环列表
 * 
 */

using System;
using UnityEngine;


namespace SuperScrollView
{
    public class SuperTreeView : MonoBehaviour
    {
        Action<SuperTreeBaseItem> mClickHandler;
        Action<SuperTreeBaseItem> mShowHandler;

        public LoopListView2 mLoopListView;

        public string mTreeItemName = "ItemPrefabTree";
        public string mItemPrefabName = "ItemPrefab2";

        TreeViewDataSource mTreeViewDataSource = null;

        // an helper class for TreeView item showing.
        TreeViewItemCountMgr mTreeItemCountMgr = new TreeViewItemCountMgr();

        public void Init(Action<SuperTreeBaseItem> showItemFunc, Action<SuperTreeBaseItem> selectFcunc)
        {
            int totalCount = -1;
            mShowHandler = showItemFunc;
            mClickHandler = selectFcunc;
            mLoopListView.InitListView(totalCount, OnGetItemByIndex);
        }

        public void SetItemPrefabName(string prefabName)
        {
            mItemPrefabName = prefabName;
        }
        virtual public LoopListViewItem2 OnGetItemByIndex(LoopListView2 listView, int index)
        {
            if (index < 0)
            {
                return null;
            }
            TreeViewItemCountData countData = mTreeItemCountMgr.QueryTreeItemByTotalIndex(index);
            if (countData == null)
            {
                return null;
            }
            int treeItemIndex = countData.mTreeItemIndex;
            TreeViewItemData treeViewItemData = mTreeViewDataSource.GetItemDataByIndex(treeItemIndex);
            if (countData.IsChild(index) == false)// if is a TreeItem
            {
                //get a new TreeItem
                LoopListViewItem2 item = listView.NewListViewItem(mTreeItemName);
                SuperTreeItem itemScript = item.GetComponent<SuperTreeItem>();
                if (item.IsInitHandlerCalled == false)
                {
                    item.IsInitHandlerCalled = true;
                    itemScript.Init();
                    itemScript.OnClickSelect(this.OnSelectItem);
                    itemScript.OnItemShow(this.OnItemShow);
                    itemScript.SetClickCallBack(this.OnExpandClicked);
                }
                bool isCanExpand = treeViewItemData.ChildCount > 0;
                itemScript.SetItemData(treeItemIndex, countData.mIsExpand, isCanExpand);
                return item;
            }
            else// if is a TreeChildItem
            {
                //childIndex is from 0 to ChildCount.
                //for example, TreeChildItem0_0 is the 0'th child of TreeItem0
                //and TreeChildItem1_2 is the 2'th child of TreeItem1
                int childIndex = countData.GetChildIndex(index);
                if (!treeViewItemData.IsVaild(childIndex))
                {
                    return null;
                }
                //get a new TreeChildItem
                LoopListViewItem2 item = listView.NewListViewItem(mItemPrefabName);
                SuperTreeChildItem itemScript = item.GetComponent<SuperTreeChildItem>();
                if (item.IsInitHandlerCalled == false)
                {
                    item.IsInitHandlerCalled = true;
                    itemScript.Init();
                    itemScript.OnClickSelect(this.OnSelectItem);
                    itemScript.OnItemShow(this.OnItemShow);
                }
                itemScript.SetItemData(treeItemIndex, childIndex);
                return item;
            }
        }

        public void OnExpandClicked(int index)
        {
            mTreeItemCountMgr.ToggleItemExpand(index);
            mLoopListView.SetListItemCount(mTreeItemCountMgr.GetTotalItemAndChildCount(), false);
            mLoopListView.RefreshAllShownItem();
        }

        void OnSelectItem(SuperTreeBaseItem item)
        {
            mClickHandler?.Invoke(item);
        }

        void OnItemShow(SuperTreeBaseItem item)
        {
            mShowHandler?.Invoke(item);
        }

        virtual public void SetData(TreeViewDataSource data, bool resetPos = false)
        {
            mTreeViewDataSource = data;

            mTreeItemCountMgr.Clear();
            int count = mTreeViewDataSource.TreeViewItemCount;
            //tells mTreeItemCountMgr there are how many TreeItems and every TreeItem has how many ChildItems.
            for (int i = 0; i < count; ++i)
            {
                var treeItemData = mTreeViewDataSource.GetItemDataByIndex(i);
                //second param "true" tells mTreeItemCountMgr this TreeItem is in expand status, that is to say all its children are showing.
                mTreeItemCountMgr.AddTreeItem(treeItemData.ChildCount, treeItemData.mDefaultExpand);
            }
            RefreshList(resetPos);
        }

        public void RefreshList(bool resetPos = false)
        {
            int count = mTreeItemCountMgr.GetTotalItemAndChildCount();
            if (mLoopListView.ItemTotalCount == count)
                mLoopListView.RefreshAllShownItem();
            else
            {
                mLoopListView.SetListItemCount(count, resetPos);
                if (!resetPos)
                    RefreshList();
            }
        }

        public void MovePanelToItemIndex(int itemIndex, int childIndex)
        {
            TreeViewItemCountData itemCountData = mTreeItemCountMgr.GetTreeItem(itemIndex);
            if (itemCountData == null)
            {
                return;
            }
            int finalIndex;
            int childCount = itemCountData.mChildCount;
            if (itemCountData.mIsExpand == false || childCount == 0 || childIndex == 0)
            {
                finalIndex = itemCountData.mBeginIndex;
            }
            else
            {
                if (childIndex > childCount)
                {
                    childIndex = childCount;
                }
                if (childIndex < 1)
                {
                    childIndex = 1;
                }
                finalIndex = itemCountData.mBeginIndex + childIndex;
            }
            mLoopListView.MovePanelToItemIndex(finalIndex, 0);
        }

        public void DoExpandAllItem()
        {
            int count = mTreeItemCountMgr.TreeViewItemCount;
            for (int i = 0; i < count; ++i)
            {
                mTreeItemCountMgr.SetItemExpand(i, true);
            }
            RefreshList();
        }

        public void DoCollapseAllItem()
        {
            int count = mTreeItemCountMgr.TreeViewItemCount;
            for (int i = 0; i < count; ++i)
            {
                mTreeItemCountMgr.SetItemExpand(i, false);
            }
            RefreshList();
        }
    }
}




